package com.fingard.dsp.bank.directbank.hnrcb01;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.bankInterface.ITransaction;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7515TodayTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7516HisTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.RetAtsTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.detail.RetAtsTransDetail;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class HNRCB01Transaction extends HNRCB01Base implements ITransaction {
    @Override
    public RetAtsTrans d_7516_HisTrans(Req7516HisTrans p_req7516) throws Exception {
        //历史明细查询返回ATS的对象
        RetAtsTrans retAts = new RetAtsTrans(p_req7516.reqHeader);
        retAts.writeStart();//写返回ATS的统一头部信息
        String tmpRespInfo = "";
        StringBuilder message = new StringBuilder();
        int succeCount = 0;
        try {
            Calendar tmpCalendarFrom = Calendar.getInstance();
            tmpCalendarFrom.setTime(p_req7516.getDateFrom());

            Calendar tmpCalendarTo = Calendar.getInstance();
            tmpCalendarTo.setTime(p_req7516.getDateTo());

            //按自然月循环查询
            int tmpIntDateFrom = 0;
            int tmpIntDateTo = 0;
            while (tmpIntDateFrom <= tmpIntDateTo) {
                Calendar tmpClndrStepTo = Calendar.getInstance();
                tmpClndrStepTo.setTime(tmpCalendarFrom.getTime());
                //判断是否跨月
                if (DateHelper.compareMonth(tmpCalendarFrom, tmpCalendarTo) == -1) {
                    //跨月则设置为月末
                    tmpClndrStepTo.set(Calendar.DAY_OF_MONTH, tmpClndrStepTo.getActualMaximum(Calendar.DAY_OF_MONTH));
                } else {
                    tmpClndrStepTo.setTime(tmpCalendarTo.getTime());
                }

                /**
                 * 分页循环，发送报文
                 */
                int tmpNowReadStart = 1;//起始笔数
                int tmpNowReadNum = 0;//已查询笔数
                Map<String, Integer> tmpTotalNum = new HashMap<String, Integer>();
                while (tmpNowReadNum == 0 || tmpNowReadNum < tmpTotalNum.get("totalCount")) {
                    JSONObject reqJson = new JSONObject();//发给银行的json报文

                    //Body
                    JSONObject bodyJson = new JSONObject();
                    bodyJson.put("ACCTNO", p_req7516.actNum);//客户账号
                    bodyJson.put("ACCTSEQNO", "");//子账户序号 非必输
                    bodyJson.put("CCYCD", convertCurToBank(p_req7516.actCur));//货币代号
                    bodyJson.put("CASHREMITFLG", "");//钞汇标志 非必输
                    bodyJson.put("STARTDATE", Format.Date8Format.format(tmpCalendarFrom.getTime()));//起始日期
                    bodyJson.put("ENDDATE", Format.Date8Format.format(tmpClndrStepTo.getTime()));//终止日期
                    bodyJson.put("STARTCNT", tmpNowReadStart + "");//起始笔数
                    bodyJson.put("INQRNGCNT", Integer.valueOf(getBankConfig().getValueAsString("pageSize")));//查询笔数
                    String orggrpid = getBankConfig().getMapValueByKey("ORGGRPID", p_req7516.actNum);
                    if (StringHelper.isNullOrEmpty(orggrpid)) {
                        orggrpid = "0000";
                    }
                    bodyJson.put("ORGGRPID", orggrpid);//集团ID 非集团账户默认值0000
                    reqJson.put("body", bodyJson);

                    //head
                    HNRCB01Header hnrcb01Header = new HNRCB01Header();
                    String customerNum = getBankConfig().getValueAsString("customerNum");//13位客户号
                    String indexno = getQryTransID();//11位序列
                    hnrcb01Header.reqSeqno = Format.Date8Format.format(new Date()) + customerNum + indexno;
                    hnrcb01Header.trsCode = "sigleAcctDetailQuery";

                    //加签字段
                    //BRANCHID|USERID|USERNAME|ENTOPERID|ENTOPERNAME|REQSEQNO|ACCTNO|ORGGRPID
                    StringBuilder signaturedata = new StringBuilder();
                    signaturedata.append(bankFront.org).append("|");//BRANCHID 签约机构号
                    signaturedata.append(bankFront.loginName).append("|");//USERID 用户号
                    signaturedata.append(bankFront.corpNo).append("|");//USERNAME 客户姓名
                    signaturedata.append(bankFront.operator).append("|");//ENTOPERID 企网操作员ID
                    signaturedata.append(bankFront.userName).append("|");//ENTOPERNAME 企网操作员姓名
                    signaturedata.append(hnrcb01Header.reqSeqno).append("|");//REQSEQNO 流水号
                    signaturedata.append(bodyJson.get("ACCTNO")).append("|");//ACCTNO 客户账号
                    signaturedata.append(orggrpid);//ORGGRPID 集团ID
                    /**
                     * 发送验签报文xml
                     */
                    XmlTextWriter writerXml = new XmlTextWriter();
                    writeSignXml(writerXml, signaturedata.toString());
                    String signDateStr[] = sendToBankBySign(writerXml.toXmlString());
                    String sign = "";
                    if (signDateStr[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(signDateStr[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            if (signDateStr[1].contains("signed_data")) {
                                sign = tmpBkReader.getFirstText("/msg/msg_body/signed_data");
                            }
                            if (StringHelper.isNullOrEmpty(sign)) {
                                //不用xml读取方式，用字符串截取 是因为测试的时候发现如果报错，银行前置
                                //返回报文格式是错误的缺少xml报文头开始标签
                                int errorStart = signDateStr[1].indexOf("<error_no>");
                                int errorEnd = signDateStr[1].indexOf("</error_no>");
                                String errorMsg = signDateStr[1].substring(errorStart + 10, errorEnd);
                                retAts.writeRespCode("-1");
                                retAts.writeRespInfo("加签失败,前置返回:" + errorMsg);
                                retAts.writeEnd();
                                return retAts;
                            }
                        } else {
                            retAts.writeRespCode("-1");
                            retAts.writeRespInfo("加签失败：" + tmpSbMsg.toString());
                            retAts.writeEnd();
                            return retAts;
                        }
                    } else {
                        retAts.writeRespCode("-1");
                        retAts.writeRespInfo("加签失败：" + signDateStr[0]);
                        retAts.writeEnd();
                        return retAts;
                    }
                    hnrcb01Header.signaturedata = sign;
                    writeCommonHeader(hnrcb01Header, reqJson);
                    String[] tmpStrRet = sendToBank(reqJson.toJSONString(), p_req7516.reqHeader.transType, p_req7516.reqHeader.commandCode);
//                    String[] tmpStrRet = {"", "{\"CUSTNM\":\"超级飞侠总超市\",\"STATUS\":\"1\",\"TTLCNT\":\"0\",\"MSG\":\"交易成功\"}"};
                    if (tmpStrRet[0].length() == 0) {
                        JSONObject resultObj = JSONObject.parseObject(tmpStrRet[1]);
                        //state：返回状态，1代表成功，msg是失败提示
                        String state = resultObj.getString("STATUS");
                        String msg = resultObj.getString("MSG");
                        if (state != null && state.equals("1")) {
                            String totalCount = resultObj.getString("TTLCNT");
                            if (tmpTotalNum.containsKey("totalCount")) {
                                if (!tmpTotalNum.get("totalCount").equals(Integer.valueOf(totalCount))) {
                                    tmpRespInfo = "查询时间：" + Format.Date8Format.format(tmpCalendarFrom.getTime()) + "到" + Format.Date8Format.format(tmpCalendarTo.getTime()) + ",起始页数:" + tmpNowReadStart + ",相同条件前后查出来的总数不一致; ";
                                    message.append(tmpRespInfo);
                                }
                            } else {
                                if ("0".equals(totalCount)) {
                                    break;
                                }
                                tmpTotalNum.put("totalCount", Integer.valueOf(totalCount));//记录总条数
                            }
                            int readCount = 0;
                            JSONArray dataList = resultObj.getJSONArray("LIST");
                            for (int i = 0; i < dataList.size(); i++) {
                                JSONObject dataObj = dataList.getJSONObject(i);
                                RetAtsTransDetail tmpRetDetail = new RetAtsTransDetail();
                                tmpRetDetail.actArea = p_req7516.actArea;//银行地区区域码
                                tmpRetDetail.actNum = p_req7516.actNum;//银行账号
                                tmpRetDetail.cur = convertCurToATS(dataObj.getString("CCYCD"));
                                String cdFlag = dataObj.getString("DBTCRTEDFLG");//行方：0-借1-贷
                                String payAmount = dataObj.getString("DBTOCCAMT");//借方发生额
                                String recAmount = dataObj.getString("CRTEDOCCAMT");//贷方发生额
                                if (cdFlag.equals("0")) {
                                    tmpRetDetail.cdFlag = "1";//1：借（支出）
                                    tmpRetDetail.tranAmt = Math.abs(Double.parseDouble(payAmount)) + "";//交易金额
                                } else {
                                    tmpRetDetail.cdFlag = "2";//2：贷（收入）
                                    tmpRetDetail.tranAmt = Math.abs(Double.parseDouble(recAmount)) + "";//交易金额
                                }
                                tmpRetDetail.accBal = dataObj.getString("ACCTNOBAL");//账户余额
                                tmpRetDetail.recAccNum = dataObj.getString("OTHERSIDEACCTNO");//对方账号
                                tmpRetDetail.recAccName = dataObj.getString("OTHERSIDENM");//对方户名
                                String tranDate = dataObj.getString("DATE");//交易日期
                                tmpRetDetail.tranDate = tranDate.substring(0, 4) + "-" + tranDate.substring(4, 6) + "-" + tranDate.substring(6, 8);
                                String tranTime = dataObj.getString("TLRTIME");//交易时间 接口文档为Int 类型
                                if (tranTime.length() == 6) {
                                    tranTime = tmpRetDetail.tranDate + " " + tranTime.substring(0, 2) + ":" + tranTime.substring(2, 4) + ":" + tranTime.substring(4, 6);
                                } else {
                                    tranTime = tmpRetDetail.tranDate + " 00:00:00";
                                }
                                tmpRetDetail.tranTime = tranTime;
                                tmpRetDetail.valueDate = tmpRetDetail.tranDate;
                                tmpRetDetail.abstr = dataObj.getString("MEMO");//支付时将对账码放入备注
                                retAts.writeRetDetail(tmpRetDetail);
                                readCount++;
                            }
                            tmpNowReadNum += readCount;//已查询条数
                            if (Integer.parseInt(totalCount) > tmpNowReadNum) {
                                //总条数大于已查询条数，说明查询了默认条数的明细
                                if (readCount != Integer.valueOf(getBankConfig().getValueAsString("pageSize"))) {
                                    retAts.writeRespCode("-1");
                                    retAts.writeRespInfo("总条数大于已查询条数,统计明细有误");
                                    retAts.writeEnd();
                                    return retAts;
                                }
                            }
                            if (Integer.parseInt(totalCount) < tmpNowReadNum) {
                                //总条数小于已查询条数,说明数据异常
                                retAts.writeRespCode("-1");
                                retAts.writeRespInfo("总条数小于已查询条数,统计明细有误");
                                retAts.writeEnd();
                                return retAts;
                            }
                            tmpNowReadStart += readCount;//查询起始笔数
                        } else {
                            tmpRespInfo = "查询时间：" + Format.Date8Format.format(tmpCalendarFrom.getTime()) + "到" + Format.Date8Format.format(tmpCalendarTo.getTime()) + ",起始页数:" + tmpNowReadStart + ",查询失败：" + msg + "; ";
                            message.append(tmpRespInfo);
                            break;
                        }
                    } else {
                        tmpRespInfo = "查询时间：" + Format.Date8Format.format(tmpCalendarFrom.getTime()) + "到" + Format.Date8Format.format(tmpCalendarTo.getTime()) + ",起始页数:" + tmpNowReadStart + ",查询失败：" + tmpStrRet[0] + "; ";
                        message.append(tmpRespInfo);
                        break;
                    }
                }
                tmpCalendarFrom = tmpClndrStepTo;
                tmpCalendarFrom.add(Calendar.DAY_OF_MONTH, 1);//下个月
                tmpIntDateFrom = Integer.parseInt(Format.Date8Format.format(tmpCalendarFrom.getTime()));
                tmpIntDateTo = Integer.parseInt(Format.Date8Format.format(tmpCalendarTo.getTime()));
            }
        } catch (Exception e) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(e.getMessage());
            e.printStackTrace();
            retAts.writeEnd();
            return retAts;
        }
        if (succeCount == 0 && message.length() == 0) {
            retAts.writeRespCode("0");
            retAts.writeRespInfo("交易为空!");
        } else if (message.length() > 0 && succeCount > 0) {
            retAts.writeRespCode("0");
            retAts.writeRespInfo(message.toString());
        } else if (succeCount == 0 && message.length() > 0) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(message.toString());
        }
        retAts.writeEndWithoutInsertDB();
        return retAts;
    }

    @Override
    public RetAtsTrans d_7515_TodayTrans(Req7515TodayTrans p_req7515) throws Exception {
        Req7516HisTrans p_req7516 = new Req7516HisTrans(p_req7515.reqHeader);
        p_req7516.actArea = p_req7515.actArea;
        p_req7516.actCur = p_req7515.actCur;
        p_req7516.actNum = p_req7515.actNum;
        String date = Format.Date8Format.format(new Date());
        p_req7516.dateFrom = date;
        p_req7516.dateTo = date;
        return d_7516_HisTrans(p_req7516);
    }
}
